package logger

import (
	"context"
	"strings"

	"go.uber.org/zap"
	"google.golang.org/grpc/metadata"
)

var defLogger *Logger

func Default() *Logger {
	return defLogger
}

func SetDefault(l *Logger) {
	defLogger = l
}

func NewLogger(options ...Option) *Logger {
	return InitLogger(options...)
}

func WithContext(ctx context.Context) *zap.SugaredLogger {
	var fields []interface{}
	for _, v := range defLogger.config.Field {
		fields = append(fields, zap.String(v, valueFromContext(ctx, v)))
	}
	return defLogger.With(fields...)
}

func Debug(args ...interface{}) {
	defLogger.Debug(args...)
}

func Debugf(format string, args ...interface{}) {
	defLogger.Debugf(format, args...)
}

func Debugw(msg string, kvs ...interface{}) {
	defLogger.Debugw(msg, kvs...)
}

func Info(args ...interface{}) {
	defLogger.Info(args...)
}

func Infof(format string, args ...interface{}) {
	defLogger.Infof(format, args...)
}

func Infow(msg string, kvs ...interface{}) {
	defLogger.Infow(msg, kvs...)
}

func Warn(args ...interface{}) {
	defLogger.Warn(args...)
}

func Warnf(format string, args ...interface{}) {
	defLogger.Warnf(format, args...)
}

func Warnw(msg string, kvs ...interface{}) {
	defLogger.Warnw(msg, kvs...)
}

func Fatal(args ...interface{}) {
	defLogger.Fatal(args...)
}

func Fatalf(format string, args ...interface{}) {
	defLogger.Fatalf(format, args...)
}

func Fatalw(msg string, kvs ...interface{}) {
	defLogger.Fatalw(msg, kvs...)
}

func Error(v ...interface{}) {
	defLogger.Error(v)
}

func Errorf(format string, args ...interface{}) {
	defLogger.Errorf(format, args...)
}

func Errorw(msg string, kvs ...interface{}) {
	defLogger.Errorw(msg, kvs...)
}

func Panic(args ...interface{}) {
	defLogger.Panic(args...)
}

func Panicf(format string, args ...interface{}) {
	defLogger.Panicf(format, args...)
}

func Panicw(msg string, kvs ...interface{}) {
	defLogger.Panicw(msg, kvs...)
}

// 获取grpc的metaData
func valueFromContext(ctx context.Context, key string) string {
	if ctx == nil {
		return ""
	}
	key = strings.ToLower(key) // grpc的metaData会将key自动转为小写
	if md, ok := metadata.FromIncomingContext(ctx); ok && len(md[key]) > 0 {
		return md[key][0]
	}
	return ""
}
